package br.senai.sc.web.pontosColeta.beans;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;

import org.jboss.seam.international.status.Messages;
import org.jboss.seam.international.status.builder.BundleKey;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;

import br.senai.sc.controller.Qualidade;
import br.senai.sc.controller.business.CorpoHidricoBusiness;
import br.senai.sc.controller.crud.BaciaHidrograficaCRUD;
import br.senai.sc.controller.crud.CorpoHidricoCRUD;
import br.senai.sc.controller.crud.FotoCRUD;
import br.senai.sc.controller.crud.PontoColetaCRUD;
import br.senai.sc.controller.exception.BusinessException;
import br.senai.sc.model.Amostra;
import br.senai.sc.model.BaciaHidrografica;
import br.senai.sc.model.CorpoHidrico;
import br.senai.sc.model.Foto;
import br.senai.sc.model.PontoColeta;
import br.senai.sc.util.SystemConstants;
import br.senai.sc.web.util.WebUtils;

/**
 * @author Fernando Marquardt &lt;fernando.marquardt@sc.senai.br&gt;
 * @since 31/01/2012
 * @version $Id: PontosColetaBean.java 30 2012-03-08 20:16:18Z
 *          fernando.marquardt $
 */
@Named
@ViewScoped
public class PontosColetaBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Inject
	private BaciaHidrograficaCRUD baciaHidrograficaCRUD;

	@Inject
	private PontoColetaCRUD pontoColetaCRUD;

	@Inject
	private CorpoHidricoCRUD corpoHidricoCRUD;

	@Inject
	private CorpoHidricoBusiness corpoHidricoBusiness;

	@Inject
	private Messages messages;

	private PontoColeta pontoColeta;

	@Inject
	private FotoCRUD fotoCRUD;

	private Foto foto;

	private DataModel<PontoColeta> pontosColeta;

	private BaciaHidrografica baciaHidrograficaSelecionada;

	public void cadastrarPontoColeta() {
		pontoColeta = new PontoColeta();
	}

	public void carregarPontoColeta() {
		pontoColeta = pontoColetaCRUD.findPontoColeta(pontosColeta.getRowData()
				.getIdPontoColeta());

		BaciaHidrografica baciaDoPonto = baciaHidrograficaCRUD
				.findBaciaHidrografica(pontoColeta.getCorpoHidrico()
						.getBaciaHidrografica().getIdBaciaHidrografica());

		// TODO task Fix para LazyInitializationException
		baciaDoPonto.getCidades().size();
		pontoColeta.getFotos().size();
		baciaHidrograficaSelecionada = baciaDoPonto;
	}

	/**
	 * Utilizado para verificar a renderização o cadastro de {@link PontoColeta}
	 * . Se não houver {@link CorpoHidrico} cadastrado deve apresentar mensagem
	 * para o usuário.
	 * 
	 * @return
	 */
	public boolean existeCorpoHidrico() {
		return corpoHidricoBusiness.existeCorpoHidrico();
	}

	public void salvarPontoColeta() {

		try {
			pontosColeta = null;
			pontoColeta = pontoColetaCRUD.salvar(pontoColeta);
			messages.info(new BundleKey(
					SystemConstants.PATH_TO_APPLICATION_MESSAGES,
					"pontosColeta.cadastrar.sucesso"));

		} catch (BusinessException e) {
		}
	}

	public void removerPontoColeta() {

		try {
			pontoColetaCRUD.remover(pontoColeta);
			pontoColeta = null;
			pontosColeta = null;
			messages.info(new BundleKey(
					SystemConstants.PATH_TO_APPLICATION_MESSAGES,
					"pontosColeta.remover.sucesso"));
		} catch (BusinessException e) {
		}
	}

	public void atualizarBaciaHidrografica() {

		baciaHidrograficaSelecionada = baciaHidrograficaCRUD
				.findBaciaHidrografica(baciaHidrograficaSelecionada
						.getIdBaciaHidrografica());
		// TODO task Fix para LazyInitializationException
		baciaHidrograficaSelecionada.getCidades().size();

	}

	public MapModel getMarcadoresMapa() {
		if (isMostrarMapa()) {
			MapModel marcadores = new DefaultMapModel();
			LatLng coordenada = new LatLng(pontoColeta.getLatitude()
					.doubleValue(), pontoColeta.getLongitude().doubleValue());

			Amostra ultimaAmostra = pontoColetaCRUD
					.findUltimaAmostra(pontoColeta.getIdPontoColeta());
			BigDecimal iqa = ultimaAmostra != null ? ultimaAmostra.getIQA()
					: BigDecimal.ZERO;

			String icon = getIconeMarcador(iqa);

			marcadores.addOverlay(new Marker(coordenada, pontoColeta.getNome(),
					null, icon));

			return marcadores;
		}

		return null;
	}

	public boolean isMostrarMapa() {
		return (pontoColeta != null) && (pontoColeta.getLatitude() != null)
				&& (pontoColeta.getLongitude() != null);
	}

	public boolean isMostrarBotaoRemover() {
		// TODO Modifica método para verificar se não existem amostras
		// cadastradas para este ponto.
		return true;
	}

	public DataModel<PontoColeta> getPontosColeta() {
		if (pontosColeta == null) {
			pontosColeta = new ListDataModel<PontoColeta>(
					pontoColetaCRUD.findPontosColeta());
		}

		return pontosColeta;
	}

	public List<BaciaHidrografica> getBaciasHidrograficas() {
		return baciaHidrograficaCRUD.findBaciasHidrograficas();
	}

	/**
	 * @return Lista de {@link CorpoHidrico} da {@link br.senai.sc.model.Cidade}
	 *         selecionada para o {@link PontoColeta}.
	 */
	public List<CorpoHidrico> getCorposHidricos() {
		if (pontoColeta.getCidade() != null) {
			return corpoHidricoCRUD.findCorposHidricos(pontoColeta.getCidade());
		}

		return null;
	}

	public PontoColeta getPontoColeta() {
		return pontoColeta;
	}

	public void setPontoColeta(PontoColeta pontoColeta) {
		this.pontoColeta = pontoColeta;
	}

	public String getIconeMarcador(BigDecimal iqa) {
		String nomeImagem = "ponto-branco.png";

		switch (Qualidade.getQualidade(iqa)) {
		case OTIMA:
			nomeImagem = "ponto-azul.png";
			break;
		case BOA:
			nomeImagem = "ponto-verde.png";
			break;
		case ACEITAVEL:
			nomeImagem = "ponto-amarelo.png";
			break;
		case RUIM:
			nomeImagem = "ponto-vermelho.png";
			break;
		case PESSIMA:
			nomeImagem = "ponto-preto.png";
			break;
		case DESCONHECIDA:
		default:
			nomeImagem = "ponto-branco.png";
		}

		return FacesContext.getCurrentInstance().getApplication()
				.getResourceHandler().createResource(nomeImagem, "img")
				.getRequestPath();
	}

	public BaciaHidrografica getBaciaHidrograficaSelecionada() {
		return baciaHidrograficaSelecionada;
	}

	public void setBaciaHidrograficaSelecionada(
			BaciaHidrografica baciaHidrograficaSelecionada) {
		this.baciaHidrograficaSelecionada = baciaHidrograficaSelecionada;
	}

	/**
	 * Para cada imagem feita upload passa por este método.
	 * 
	 * @param event
	 */
	public void handleFileUpload(FileUploadEvent event) {

		pontoColeta.getFotos().add(WebUtils.createFoto(event.getFile()));
		try {
			pontoColeta = pontoColetaCRUD.salvar(pontoColeta);
			pontoColetaCRUD.flush();
		} catch (BusinessException e) {
		}
	}

	/**
	 * Remove a {@link Foto} carregada.
	 * 
	 * @see PontosColetaBean#carregarImagem(Foto).
	 */
	public void removerFoto() {

		pontoColeta.getFotos().remove(foto);
		try {
			pontoColetaCRUD.salvar(pontoColeta);
			pontoColetaCRUD.flush();
			fotoCRUD.remover(foto);
		} catch (BusinessException e) {
		}
	}

	/**
	 * Carrega a {@link Foto} para as opções (ex: remover).
	 * 
	 * @param foto
	 */
	public void carregarImagem(Foto foto) {
		this.foto = foto;
	}

}